(function () {
    var browser = baidu.editor.browser,
        domUtils = baidu.editor.dom.domUtils;

    var magic = "$EDITORUI";
    var root = (window[magic] = {});
    var uidMagic = "ID" + magic;
    var uidCount = 0;

    var uiUtils = (baidu.editor.ui.uiUtils = {
        uid: function (obj) {
            return obj ? obj[uidMagic] || (obj[uidMagic] = ++uidCount) : ++uidCount;
        },
        hook: function (fn, callback) {
            var dg;
            if (fn && fn._callbacks) {
                dg = fn;
            } else {
                dg = function () {
                    var q;
                    if (fn) {
                        q = fn.apply(this, arguments);
                    }
                    var callbacks = dg._callbacks;
                    var k = callbacks.length;
                    while (k--) {
                        var r = callbacks[k].apply(this, arguments);
                        if (q === undefined) {
                            q = r;
                        }
                    }
                    return q;
                };
                dg._callbacks = [];
            }
            dg._callbacks.push(callback);
            return dg;
        },
        createElementByHtml: function (html) {
            var el = document.createElement("div");
            el.innerHTML = html;
            el = el.firstChild;
            el.parentNode.removeChild(el);
            return el;
        },
        getViewportElement: function () {
            return browser.ie && browser.quirks
                ? document.body
                : document.documentElement;
        },
        getClientRect: function (element) {
            var bcr;
            //trace  IE6下在控制编辑器显隐时可能会报错，catch一下
            try {
                bcr = element.getBoundingClientRect();
            } catch (e) {
                bcr = {left: 0, top: 0, height: 0, width: 0};
            }
            var rect = {
                left: Math.round(bcr.left),
                top: Math.round(bcr.top),
                height: Math.round(bcr.bottom - bcr.top),
                width: Math.round(bcr.right - bcr.left)
            };
            var doc;
            while (
                (doc = element.ownerDocument) !== document &&
                (element = domUtils.getWindow(doc).frameElement)
                ) {
                bcr = element.getBoundingClientRect();
                rect.left += bcr.left;
                rect.top += bcr.top;
            }
            rect.bottom = rect.top + rect.height;
            rect.right = rect.left + rect.width;
            return rect;
        },
        getViewportRect: function () {
            var viewportEl = uiUtils.getViewportElement();
            var width = (window.innerWidth || viewportEl.clientWidth) | 0;
            var height = (window.innerHeight || viewportEl.clientHeight) | 0;
            return {
                left: 0,
                top: 0,
                height: height,
                width: width,
                bottom: height,
                right: width
            };
        },
        setViewportOffset: function (element, offset) {
            var rect;
            var fixedLayer = uiUtils.getFixedLayer();
            if (element.parentNode === fixedLayer) {
                element.style.left = offset.left + "px";
                element.style.top = offset.top + "px";
            } else {
                domUtils.setViewportOffset(element, offset);
            }
        },
        getEventOffset: function (evt) {
            var el = evt.target || evt.srcElement;
            var rect = uiUtils.getClientRect(el);
            var offset = uiUtils.getViewportOffsetByEvent(evt);
            return {
                left: offset.left - rect.left,
                top: offset.top - rect.top
            };
        },
        getViewportOffsetByEvent: function (evt) {
            var el = evt.target || evt.srcElement;
            var frameEl = domUtils.getWindow(el).frameElement;
            var offset = {
                left: evt.clientX,
                top: evt.clientY
            };
            if (frameEl && el.ownerDocument !== document) {
                var rect = uiUtils.getClientRect(frameEl);
                offset.left += rect.left;
                offset.top += rect.top;
            }
            return offset;
        },
        setGlobal: function (id, obj) {
            root[id] = obj;
            return magic + '["' + id + '"]';
        },
        unsetGlobal: function (id) {
            delete root[id];
        },
        copyAttributes: function (tgt, src) {
            var attributes = src.attributes;
            var k = attributes.length;
            while (k--) {
                var attrNode = attributes[k];
                if (
                    attrNode.nodeName != "style" &&
                    attrNode.nodeName != "class" &&
                    (!browser.ie || attrNode.specified)
                ) {
                    tgt.setAttribute(attrNode.nodeName, attrNode.nodeValue);
                }
            }
            if (src.className) {
                domUtils.addClass(tgt, src.className);
            }
            if (src.style.cssText) {
                tgt.style.cssText += ";" + src.style.cssText;
            }
        },
        removeStyle: function (el, styleName) {
            if (el.style.removeProperty) {
                el.style.removeProperty(styleName);
            } else if (el.style.removeAttribute) {
                el.style.removeAttribute(styleName);
            } else throw "";
        },
        contains: function (elA, elB) {
            return (
                elA &&
                elB &&
                (elA === elB
                    ? false
                    : elA.contains
                        ? elA.contains(elB)
                        : elA.compareDocumentPosition(elB) & 16)
            );
        },
        startDrag: function (evt, callbacks, doc) {
            var doc = doc || document;
            var startX = evt.clientX;
            var startY = evt.clientY;

            function handleMouseMove(evt) {
                var x = evt.clientX - startX;
                var y = evt.clientY - startY;
                callbacks.ondragmove(x, y, evt);
                if (evt.stopPropagation) {
                    evt.stopPropagation();
                } else {
                    evt.cancelBubble = true;
                }
            }

            if (doc.addEventListener) {
                function handleMouseUp(evt) {
                    doc.removeEventListener("mousemove", handleMouseMove, true);
                    doc.removeEventListener("mouseup", handleMouseUp, true);
                    window.removeEventListener("mouseup", handleMouseUp, true);
                    callbacks.ondragstop();
                }

                doc.addEventListener("mousemove", handleMouseMove, true);
                doc.addEventListener("mouseup", handleMouseUp, true);
                window.addEventListener("mouseup", handleMouseUp, true);

                evt.preventDefault();
            } else {
                var elm = evt.srcElement;
                elm.setCapture();

                function releaseCaptrue() {
                    elm.releaseCapture();
                    elm.detachEvent("onmousemove", handleMouseMove);
                    elm.detachEvent("onmouseup", releaseCaptrue);
                    elm.detachEvent("onlosecaptrue", releaseCaptrue);
                    callbacks.ondragstop();
                }

                elm.attachEvent("onmousemove", handleMouseMove);
                elm.attachEvent("onmouseup", releaseCaptrue);
                elm.attachEvent("onlosecaptrue", releaseCaptrue);
                evt.returnValue = false;
            }
            callbacks.ondragstart();
        },
        getFixedLayer: function () {
            var layer = document.getElementById("edui_fixedlayer");
            if (layer == null) {
                layer = document.createElement("div");
                layer.id = "edui_fixedlayer";
                document.body.appendChild(layer);
                if (browser.ie && browser.version <= 8) {
                    layer.style.position = "absolute";
                    bindFixedLayer();
                    setTimeout(updateFixedOffset);
                } else {
                    layer.style.position = "fixed";
                }
                layer.style.left = "0";
                layer.style.top = "0";
                layer.style.width = "0";
                layer.style.height = "0";
                layer.style.margin = "0";
            }
            return layer;
        },
        makeUnselectable: function (element) {
            if (browser.opera || (browser.ie && browser.version < 9)) {
                element.unselectable = "on";
                if (element.hasChildNodes()) {
                    for (var i = 0; i < element.childNodes.length; i++) {
                        if (element.childNodes[i].nodeType === 1) {
                            uiUtils.makeUnselectable(element.childNodes[i]);
                        }
                    }
                }
            } else {
                if (element.style.MozUserSelect !== undefined) {
                    element.style.MozUserSelect = "none";
                } else if (element.style.WebkitUserSelect !== undefined) {
                    element.style.WebkitUserSelect = "none";
                } else if (element.style.KhtmlUserSelect !== undefined) {
                    element.style.KhtmlUserSelect = "none";
                }
            }
        }
    });

    function updateFixedOffset() {
        var layer = document.getElementById("edui_fixedlayer");
        uiUtils.setViewportOffset(layer, {
            left: 0,
            top: 0
        });
        //        layer.style.display = 'none';
        //        layer.style.display = 'block';

        //#trace: 1354
        //        setTimeout(updateFixedOffset);
    }

    function bindFixedLayer(adjOffset) {
        domUtils.on(window, "scroll", updateFixedOffset);
        domUtils.on(
            window,
            "resize",
            baidu.editor.utils.defer(updateFixedOffset, 0, true)
        );
    }
})();
